import React, { memo, useEffect, useRef, useState, useCallback } from 'react';
import { connect } from 'umi';
import {
    Alert,
    Button,
    Card,
    DatePicker,
    Descriptions,
    Divider,
    Empty,
    Icon,
    message,
    Radio,
    Spin,
    Table,
    Tooltip,
    Typography,
    Popover
} from 'antd';
import moment from 'moment';
import cn from 'classnames';
import isEmpty from 'lodash/isEmpty';

import { withRoutePage } from '@/utils/enhanceUtils';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import { BottomAction } from '@/components';
import BizIcon from '@/components/BizIcon';

import {
    onSaveEnsureSalary,
    querySalaryConfirmDateList,
    querySalaryConfirmInfo
} from '@/services/salaryManage/salaryConfirm';
import { salaryPayrollPrint } from '@/services/salaryManage/mySalary';
import { getCurrentCompanyCode, getCurrentCountryCode } from '@/pages/SalaryManage/utils';
import { SINGAPORE_CODE } from '@/pages/SalaryManage/constant/countryRegion';
import NumberFormatter from '@/pages/SalaryManage/components/NumberFormatter';
import EmptyPlaceHolder from '@/pages/SalaryManage/components/EmptyPlaceHolder';
import { commonColumn, amountSettingColumn, percentSettingColumn } from '@/pages/SalaryManage/utils/TableUtil';

import SalarySheet from '@/pages/SalaryManage/components/SalarySheet';
import FeedBackModal from '@/pages/SalaryManage/SalaryConfirm/components/FeedBackModal';
import FeedBackListModal from '@/pages/SalaryManage/SalaryConfirm/components/FeedBackListModal';
import { TaxAmtSettingDescription } from '@/pages/SalaryManage/components/TaxAmtDescription';

import salaryStyle from '@/pages/SalaryManage/salaryManage.less';
import StepList from '@/pages/SalaryManage/components/StepList';
import SensitiveInfo from '@/pages/SalaryManage/components/SensitiveInfo';
import Fishbone from '../components/Fishbone';
import styles from '../index.less';

const { Text } = Typography;
const { Group } = Radio;

const { MonthPicker } = DatePicker;
const TAX_LIST = [
    {
        label: '截止上月累计税前收入',
        key: 'encryptTotalIncomeAmt'
    },
    {
        label: '本月税前收入',
        key: 'encryptCurrIncomeAmt'
    },
    {
        label: '截止上月累计医社保（个人）',
        key: 'encryptTotalSocialAmt'
    },
    {
        label: '本月医社保（个人）',
        key: 'encryptCurrSocialAmt'
    },
    {
        label: '截止上月累计公积金（个人）',
        key: 'encryptTotalFundHouseAmt'
    },
    {
        label: '本月公积金（个人）',
        key: 'encryptFundPersonAmt'
    },
    {
        label: '截止上月累计税后加减项',
        key: 'encryptTotalAfterTaxAmt'
    },
    {
        label: '本月税后加减项',
        key: 'encryptCurrAfterTaxAmt'
    },
    {
        label: '截止上月累计免征额',
        key: 'encryptTotalExpenseAmt'
    },
    {
        label: '本月免征额',
        key: 'encryptCurrExpenseAmt'
    },
    {
        label: '截止上月累计专项扣款',
        key: 'encryptTotalSpecialAmt'
    },
    {
        label: '本月专项扣款',
        key: 'encryptCurrSpecialAmt'
    }
];

const TOTAL_TAX_LIST = [
    {
        label: '累计计税基数',
        key: 'encryptTotalTaxIncomeAmt'
    },
    {
        label: '累计应扣个税',
        key: 'encryptTotalPayableTaxAmt'
    },
    {
        label: '累计已扣个税',
        key: 'encryptTotalPayedTaxAmt'
    },
    {
        label: '本月应扣个税',
        key: 'encryptTaxAmt'
    }
];
const TAX_TABLE_COLUMN = [
    commonColumn({
        title: '级数',
        dataIndex: 'taxLevel',
        key: 'taxLevel',
        width: 120,
        align: 'center'
    }),
    commonColumn({
        title: '累计预扣预缴应纳所得额',
        dataIndex: 'taxLevelName',
        key: 'taxLevelName',
        render(text, record) {
            return <TaxAmtSettingDescription record={record} />;
        }
    }),
    percentSettingColumn({
        title: '预扣率（%）',
        dataIndex: 'encryptTaxRate',
        key: 'encryptTaxRate'
    }),
    amountSettingColumn({
        title: '速算扣除数',
        dataIndex: 'encryptQuickDeductAmt',
        key: 'encryptQuickDeductAmt'
    })
];
const SOCIAL_TABLE_COLUMN = [
    {
        title: '字段',
        dataIndex: 'name',
        key: 'name',
        align: 'left'
    },
    {
        title: '缴费基数',
        dataIndex: 'encryptBaseAmt',
        key: 'encryptBaseAmt',
        align: 'right',
        columnType: 2
    },
    {
        title: '单位应缴',
        dataIndex: 'encryptCompanyAmt',
        key: 'encryptCompanyAmt',
        align: 'right',
        columnType: 2
    },
    {
        title: '个人应缴',
        dataIndex: 'encryptPersonAmt',
        key: 'encryptPersonAmt',
        align: 'right',
        columnType: 2
    },
    {
        title: '本金合计',
        dataIndex: 'encryptTotalAmt',
        key: 'encryptTotalAmt',
        align: 'right',
        columnType: 2
    }
];

const CPF_LIST = [
    {
        label: '年龄区间',
        key: 'cpfAgePeriod',
        columnType: 0
    },

    {
        label: '身份类型',
        key: 'singaporeidType',
        columnType: 0
    },

    {
        label: '公积金类型',
        key: 'cpfPayType',
        columnType: 0
    },
    {
        label: '薪资总额',
        key: 'encryptOw'
    },
    {
        label: '雇员缴交比例',
        key: 'employeeShare',
        columnType: 0
    },
    {
        label: '雇员缴交金额(当月)',
        key: 'encryptEmployeeCpfAmt'
    },
    {
        label: '雇主缴交比例',
        key: 'companyShare',
        columnType: 0
    },
    {
        label: '雇主缴交金额(当月)',
        key: 'encryptCompanyCpfAmt'
    },
    {
        label: null,
        key: null
    },
    {
        label: '合计金额(当月)',
        key: 'encryptTotalCpfAmt'
    },
    {
        label: '雇员缴交金额(累计值)',
        key: 'encryptYtdEmployeeCpfAmt'
    },
    {
        label: '雇主缴交金额(累计值)',
        key: 'encryptYtdCompanyCpfAmt'
    },
    {
        label: null,
        key: null
    },
    {
        label: '合计金额(累计值)',
        key: 'encryptYtdTotalCpfAmt'
    }
];
const SDL_TABLE_COLUMN = [
    commonColumn({
        title: '薪资总额',
        dataIndex: 'encryptTw',
        key: 'encryptTw',
        columnType: 2
    }),
    commonColumn({
        title: '技能发展税',
        dataIndex: 'encryptSdlAmt',
        key: 'encryptSdlAmt',
        columnType: 2
    }),
    commonColumn({
        title: '技能发展税（累计值）',
        dataIndex: 'encryptYtdSdlAmt',
        key: 'encryptYtdSdlAmt',
        columnType: 2
    })
];
const SHG__TABLE_COLUMN = [
    commonColumn({
        title: '种族类型',
        dataIndex: 'singaporeRace',
        key: 'singaporeRace'
    }),
    commonColumn({
        title: '薪资总额',
        dataIndex: 'encryptTw',
        key: 'encryptTw',
        columnType: 2
    }),
    commonColumn({
        title: '种族自助金',
        dataIndex: 'encryptShgAmt',
        key: 'encryptShgAmt',
        columnType: 2
    }),
    commonColumn({
        title: '种族自助金（累计值）',
        dataIndex: 'encryptYtdShgAmt',
        key: 'encryptYtdShgAmt',
        columnType: 2
    })
];
const SalaryItem = memo(({ children, title = 'title', tips = null, style = {} }) => {
    const [active, setActive] = useState(true);
    const onActiveChange = () => {
        setActive(!active);
    };
    return (
        <div className={styles.salaryItemBox} style={style}>
            <div className={styles.titleWrap}>
                <div className={styles.title}>
                    {title}
                    {tips ? (
                        <Popover
                            content={
                                <div style={{ maxWidth: 550 }}>
                                    <div>{tips?.head}：</div>
                                    <div>{tips?.content}</div>
                                </div>
                            }
                        >
                            <Icon type="question-circle" className={salaryStyle.ml8} />
                        </Popover>
                    ) : null}
                </div>
                <Button type="link" onClick={onActiveChange}>
                    {active ? '收起' : '展开'}
                    <Icon type={active ? 'up' : 'down'} />
                </Button>
            </div>
            {active ? children : null}
        </div>
    );
});
const handleHeaderData = (data = [], hideSensitive) =>
    data.map(item =>
        item.children && item.children.length
            ? {
                  ...item,
                  children: handleHeaderData(item.children, hideSensitive)
              }
            : {
                  ...item,
                  align: item.align || 'left',
                  children: null,
                  render: t =>
                      item.columnType === 2 ? (
                          <SensitiveInfo hide={hideSensitive}>
                              <NumberFormatter value={t} className={salaryStyle.currency} />
                          </SensitiveInfo>
                      ) : (
                          <EmptyPlaceHolder value={t} />
                      ),
                  width: item?.columnType === 2 ? 120 : 160
              }
    );

const SalaryItemList = memo(({ detailInfo = [], hideSensitive }) =>
    /*
    主要变更在于：1）新加坡薪资没有税前加项；2）薪资详情不体现五险一金，增加体现CPF、SHG Funds 和SDL的展示
    */
    detailInfo
        .filter(d => d.conditionItems && d.conditionItems.length)
        .map(i => ({
            ...i,
            conditionItems: handleHeaderData(i.conditionItems, hideSensitive)
        }))
        .map(item => {
            const rest = {};
            if (item.totalAmount) {
                rest.footer = () =>
                    item.totalAmount ? (
                        <>
                            合计：
                            <NumberFormatter value={item.totalAmount} className={salaryStyle.currency} />
                        </>
                    ) : null;
            }

            return (
                <SalaryItem
                    title={item.title}
                    key={item.id}
                    tips={
                        (item.funcTips && { head: '公式', content: item.funcTips }) ||
                        (item.flowTips && { head: '审批流', content: item.flowTips })
                    }
                >
                    <Table
                        columns={item.conditionItems}
                        dataSource={[...item.data]}
                        bordered={false}
                        size="middle"
                        pagination={false}
                        rowKey="key"
                        className={cn(salaryStyle.borderTable, {
                            [salaryStyle.noBorderBottom]: !rest.footer
                        })}
                        scroll={{ x: 'max-content' }}
                        {...rest}
                    />
                </SalaryItem>
            );
        })
);
const TaxInfo = memo(({ taxInfo = {}, hideSensitive }) => (
    <SalaryItem title="个人所得税">
        <Card bordered title="已有纳税记录" className={styles.taxInfoCard}>
            <div className={styles.taxInfoWrap}>
                <Descriptions column={2} colon={false}>
                    {TAX_LIST.map(item => (
                        <Descriptions.Item
                            key={item.key}
                            label={
                                <span className={cn(salaryStyle.labelSecondary, styles.taxInfoItemTitle)}>
                                    {item.label}:
                                </span>
                            }
                        >
                            <SensitiveInfo hide={hideSensitive}>
                                <NumberFormatter value={taxInfo[item.key]} className={salaryStyle.currency} />
                            </SensitiveInfo>
                        </Descriptions.Item>
                    ))}
                </Descriptions>

                <Divider />

                <div className={styles.taxInfoSecondCaption}>结果展示：</div>
                <Descriptions column={2} colon={false} className={styles.taxInfoResultBody}>
                    {TOTAL_TAX_LIST.map(item => (
                        <Descriptions.Item
                            key={item.key}
                            label={<span className={cn(styles.taxInfoItemTitle)}>{item.label}:</span>}
                        >
                            <SensitiveInfo hide={hideSensitive}>
                                <NumberFormatter value={taxInfo[item.key]} className={salaryStyle.currency} />
                            </SensitiveInfo>
                        </Descriptions.Item>
                    ))}
                </Descriptions>

                <div className={styles.taxInfoSecondCaption}>参考预扣率表级数：</div>
                <Table
                    columns={TAX_TABLE_COLUMN}
                    dataSource={[taxInfo]}
                    size="middle"
                    pagination={false}
                    rowKey="key"
                    className={salaryStyle.borderTable}
                />
            </div>
        </Card>
    </SalaryItem>
));
const CPFInfo = memo(({ infoData = {}, hideSensitive }) => (
    <SalaryItem title="公积金">
        <Card bordered title="公积金计算结果" className={cn(styles.cpfInfoCard, styles.taxInfoCard)}>
            <div className={cn(styles.cpfInfoWrap, styles.taxInfoWrap)}>
                <Descriptions column={2} colon={false}>
                    {CPF_LIST.map(item => (
                        <Descriptions.Item
                            key={item.key}
                            bordered
                            label={
                                <span className={cn(salaryStyle.labelSecondary, styles.taxInfoItemTitle)}>
                                    {item.label ? `${item.label}:` : ''}
                                </span>
                            }
                        >
                            {item.columnType === 0 && item.key ? (
                                <span className={salaryStyle.currency}>
                                    <EmptyPlaceHolder value={infoData[item.key]} />
                                </span>
                            ) : null}
                            {item.columnType !== 0 && item.key ? (
                                <SensitiveInfo hide={hideSensitive}>
                                    <NumberFormatter value={infoData[item.key]} className={salaryStyle.currency} />
                                </SensitiveInfo>
                            ) : null}
                        </Descriptions.Item>
                    ))}
                </Descriptions>
            </div>
        </Card>
    </SalaryItem>
));
const StepListWrapper = memo(({ showStep, period, loadingStatus }) => {
    const [loading, setLoading] = useState(false);
    const loadingRelativeRef = useRef(null);

    useEffect(() => {
        const preValue = loadingRelativeRef.current;

        // 其中有一个值变更为true时，则重新加载
        if (
            preValue === null ||
            (showStep && showStep !== preValue.showStep) ||
            (period && period !== preValue.period) ||
            (loadingStatus && loadingStatus !== preValue.loadingStatus)
        ) {
            setLoading(true);
        }

        loadingRelativeRef.current = { showStep, period, loadingStatus };
    }, [showStep, period, loadingStatus]);

    useEffect(() => {
        if (loading) {
            const task = setTimeout(setLoading(false), 10);

            return () => {
                window.clearTimeout(task);
            };
        }
        return () => {};
    }, [loading]);

    return <>{showStep ? <StepList loading={loading} period={period} showButton={false} /> : null}</>;
});

/**
 *
 * @param period 账期，格式YYYY-MM
 * @param backlist 是否显示反馈记录，1:显示
 * @returns {JSX.Element}
 * @constructor
 */
const SalaryConfirm = ({ period, backlist }) => {
    const [isShowTips, setIsShowTips] = useState(false);
    const [loading, setLoading] = useState(false);
    const [ensureLoading, setEnsureLoading] = useState(false);
    const [salaryInfo, setSalaryInfo] = useState({});
    const [currentDate, setCurrentDate] = useState(null);
    const [detailInfoList, setDetailInfoList] = useState([]);
    const [monthRange, setMonthRange] = useState([]);
    const [feedBackListModalVisible, setFeedBackListModalVisible] = useState(false);
    const [feedBackModalVisible, setFeedBackModalVisible] = useState(false);
    const [feedbackList, setFeedbackList] = useState([]);
    const [viewType, setViewType] = useState(1);
    const [fishBoneList, setFishBoneList] = useState(null);
    const [hideSensitive, setHideSensitive] = useState(true);
    const countryCode = getCurrentCountryCode(); // 获取当前的国家
    const isSingapore = countryCode === SINGAPORE_CODE; // 是否新加坡
    const getSalaryInfo = async () => {
        try {
            setLoading(true);
            const { code, data = {} } = await querySalaryConfirmInfo({
                date: currentDate
            });
            if (code === 10000) {
                const salaryPayrollOverviewVO = data.salaryPayrollOverviewVO || {};
                const { addItems = [], lessItems = [], otherItems = [] } = salaryPayrollOverviewVO;
                setSalaryInfo(data);
                if (isSingapore) {
                    // 新加坡不展示五险一金,展示种族自助金和技能发展税
                    setDetailInfoList([
                        ...(data.salaryItemDetailVOs || {}),
                        {
                            conditionItems: SHG__TABLE_COLUMN,
                            data: data.sgSalaryPayrollShgVOs,
                            title: '种族自助金'
                        },
                        {
                            conditionItems: SDL_TABLE_COLUMN,
                            data: data.sgSalaryPayrollSdlVOs,
                            title: '技能发展税'
                        }
                    ]);
                } else {
                    setDetailInfoList([
                        ...(data.salaryItemDetailVOs || {}),
                        {
                            conditionItems: SOCIAL_TABLE_COLUMN,
                            data: data.salaryItemSocialDetailVOs,
                            title: '险金'
                        }
                    ]);
                }

                setFeedbackList([...addItems, ...lessItems, ...otherItems]);
                setIsShowTips(data.isShowTips);
                setFishBoneList(data.confirmFishBoneVO);
            } else {
                message.error('服务端异常，请重试！');
            }
            setLoading(false);
        } catch (e) {
            setLoading(false);
        }
    };
    const onEnsureSalary = async () => {
        try {
            setEnsureLoading(true);
            const { code, msg } = await onSaveEnsureSalary({
                date: currentDate || ''
            });
            if (code === 10000) {
                message.success('确认成功！');
                getSalaryInfo();
            } else {
                message.error(msg);
            }
            setEnsureLoading(false);
        } catch (e) {
            setEnsureLoading(false);
            console.error(e);
        }
    };
    const disabledDate = current => {
        const len = monthRange.length;
        if (current && len) {
            return monthRange.indexOf(current.startOf('month').format('YYYY-MM-DD')) === -1;
        }
        return false;
    };

    useEffect(() => {
        querySalaryConfirmDateList()
            .then(response => {
                const { code, data = [] } = response;
                if (code === 10000) {
                    setMonthRange(data);
                }
                setLoading(false);
            })
            .catch(() => {
                setLoading(false);
            });
    }, []);
    useEffect(() => {
        if (currentDate) {
            setLoading(true);
            getSalaryInfo();
        }
    }, [currentDate]);
    useEffect(() => {
        if (period) {
            setCurrentDate(period);
        }
    }, [period]);
    useEffect(() => {
        if (monthRange?.length > 0 && !period) {
            setCurrentDate(moment(monthRange[0]).format('YYYY-MM'));
        }
    }, [monthRange, period]);
    useEffect(() => {
        setFeedBackListModalVisible(String(backlist) === '1');
    }, [backlist]);

    // 打印薪资单
    const salaryPrint = useCallback((payrollId, dateTime) => {
        salaryPayrollPrint({
            organizationCode: getCurrentCompanyCode(),
            payrollId
        }).then(res => {
            console.log(res);
            const URL = window.URL || window.webkitURL;
            const objectUrl = URL.createObjectURL(res.data);
            const a = document.createElement('a');
            a.href = objectUrl;
            a.download = `${dateTime}薪资单`;
            document.body.appendChild(a);
            a.click();
            a.remove();
        });
    }, []);
    return (
        <PageHeaderWrapper type="success">
            <div className={cn(styles.container, salaryStyle.pt0)}>
                <div className={salaryStyle.salaryWrapper}>
                    <div className={cn(styles.header, styles.borderBottom)}>
                        薪资单
                        <Button type="link" onClick={() => setHideSensitive(!hideSensitive)}>
                            {hideSensitive ? '显示' : '隐藏'}金额
                        </Button>
                    </div>
                    {isShowTips ? (
                        <Alert message={<Text type="warning">{salaryInfo.warningTips}</Text>} closable banner />
                    ) : null}
                    <div className={cn(styles.titleWrap)} style={{ marginTop: '8px', marginBottom: '8px' }}>
                        <div className={styles.leftTitleWrap}>
                            <span className={salaryStyle.textRight} style={{ width: '70px' }}>
                                月份：
                            </span>
                            <MonthPicker
                                disabled={!monthRange.length}
                                value={currentDate ? moment(currentDate) : null}
                                format="YYYY-MM"
                                disabledDate={disabledDate}
                                placeholder="请选择"
                                onChange={(date, dateString) => {
                                    setCurrentDate(dateString);
                                }}
                                allowClear={false}
                                className={salaryStyle.mr8}
                            />
                            {currentDate ? (
                                <Button
                                    type="primary"
                                    ghost
                                    onClick={e => {
                                        e.preventDefault();
                                        setFeedBackListModalVisible(true);
                                    }}
                                    className={salaryStyle.ml8}
                                >
                                    反馈记录
                                </Button>
                            ) : null}
                            {isShowTips && salaryInfo?.feedbackAble ? (
                                <Button
                                    type="primary"
                                    ghost
                                    onClick={() => {
                                        setFeedBackModalVisible(true);
                                    }}
                                    className={salaryStyle.ml8}
                                >
                                    异常反馈
                                </Button>
                            ) : null}

                            {salaryInfo?.payrollId && isSingapore ? (
                                <Button
                                    type="primary"
                                    ghost
                                    onClick={() => salaryPrint(salaryInfo?.payrollId, currentDate)}
                                    className={salaryStyle.ml8}
                                >
                                    打印
                                </Button>
                            ) : null}
                        </div>
                    </div>
                    <Spin spinning={loading}>
                        <StepListWrapper
                            showStep={salaryInfo?.isShowProcess}
                            period={currentDate}
                            loadingStatus={loading}
                        />
                        <div className={cn(styles.salaryConfirmWrap, styles.grayContainer)}>
                            <div className={cn(styles.header, styles.borderBottom)}>薪资单</div>
                            <div className={styles.grayContainerBody}>
                                {isEmpty(salaryInfo) ? (
                                    <Empty />
                                ) : (
                                    <>
                                        <div className={styles.salarySheetWrap}>
                                            <div className={styles.salarySheetContent}>
                                                <SalarySheet
                                                    salaryData={salaryInfo.salaryPayrollOverviewVO}
                                                    hideSensitive={hideSensitive}
                                                    organizationCode={getCurrentCompanyCode()}
                                                />
                                            </div>
                                        </div>
                                        <div className={cn(styles.header, styles.borderBottom, salaryStyle.flex)}>
                                            薪资详情
                                            <Group
                                                defaultValue="1"
                                                value={viewType}
                                                className={cn(salaryStyle.switchRadio)}
                                                style={{ marginLeft: 'auto' }}
                                            >
                                                <Tooltip title="列表">
                                                    <Radio.Button value={1} onClick={() => setViewType(1)}>
                                                        <BizIcon type="zhailiebiaoshitu1" />
                                                    </Radio.Button>
                                                </Tooltip>
                                                <Tooltip title="鱼骨图">
                                                    <Radio.Button value={2} onClick={() => setViewType(2)}>
                                                        <BizIcon type="yugutu" />
                                                    </Radio.Button>
                                                </Tooltip>
                                            </Group>
                                        </div>
                                        {viewType === 1 ? (
                                            <>
                                                <SalaryItemList
                                                    detailInfo={detailInfoList}
                                                    hideSensitive={hideSensitive}
                                                />
                                                {isSingapore ? (
                                                    <CPFInfo
                                                        infoData={salaryInfo.salaryPayrollCpfVO}
                                                        hideSensitive={hideSensitive}
                                                    />
                                                ) : (
                                                    <TaxInfo
                                                        taxInfo={salaryInfo.salaryItemTaxOverviewVO}
                                                        hideSensitive={hideSensitive}
                                                    />
                                                )}
                                            </>
                                        ) : (
                                            <>
                                                {fishBoneList ? (
                                                    <Fishbone dataSource={fishBoneList} hideSensitive={hideSensitive} />
                                                ) : null}
                                            </>
                                        )}
                                    </>
                                )}
                            </div>
                        </div>
                    </Spin>
                </div>
            </div>
            <FeedBackModal
                visible={feedBackModalVisible}
                onSetVisible={setFeedBackModalVisible}
                dataList={feedbackList}
                date={currentDate}
            />
            <FeedBackListModal
                visible={feedBackListModalVisible}
                onSetVisible={setFeedBackListModalVisible}
                date={currentDate}
            />
            {isShowTips ? (
                <BottomAction>
                    <Button type="primary" loading={ensureLoading} onClick={onEnsureSalary}>
                        确认无误
                    </Button>
                </BottomAction>
            ) : null}
        </PageHeaderWrapper>
    );
};
export default withRoutePage(
    connect((state, { location }) => ({
        period: location?.query?.period,
        backlist: location?.query?.backlist
    }))(SalaryConfirm)
);
